package com.atguigu.gmall.realtime.publisher.service.impl;


import com.atguigu.gmall.realtime.publisher.bean.NameValueData;
import com.atguigu.gmall.realtime.publisher.service.OrderService;
import com.google.errorprone.annotations.Var;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    JestClient jestClient;


    private String switchTypeToField(String type){
         if(type.equals("gender")){
             return "user_gender";
         }else if(type.equals("age")){
             return "user_age";
         }
         throw new RuntimeException("unsupported type!!!");
    }


    // 根据不同的业务类型处理结果
    private List<NameValueData>  changeResultListByType(String type,List<TermsAggregation.Entry> buckets){
        List<NameValueData> nameValueDataList=new ArrayList<>();
        if(type.equals("gender")){
            //性别的处理 转换F M变为 男女
            for (TermsAggregation.Entry bucket : buckets) {
                NameValueData nameValueData=null;
                if(bucket.getKey().equals("M")){
                    nameValueData= new NameValueData("男", new BigDecimal(bucket.getCount()) );
                }else{
                    nameValueData=new NameValueData("女", new BigDecimal(bucket.getCount()) );
                }
                nameValueDataList.add(nameValueData);
            }
            return  nameValueDataList;
        }else if(type.equals("age")){
            //   作为作业：  实现把es中以年龄为单位的统计结果转换为年龄段为单位的统计结果
            //
              return nameValueDataList;
        }
        throw new RuntimeException("unsupported type!!!");
    }


    //  1  构造查询语句 searchSourceBuilder
    //  2  用jest执行语句
    //  3  接收并处理返回结果
    @Override
    public List<NameValueData> getStatsByItem(String type, String date, String itemName) {
        String groupField = switchTypeToField(type);
        //  1  构造查询语句 searchSourceBuilder
        List<NameValueData> nameValueDataList=null;

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //分词查询
        searchSourceBuilder.query(new MatchQueryBuilder("sku_name",itemName).operator(Operator.AND));
        //聚合部分
        TermsAggregationBuilder termsAggs = AggregationBuilders.terms("groupby_" + type).field(groupField).size(1000);
        searchSourceBuilder.aggregation(termsAggs);

        Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex("gmall0609_order_wide_"+date).build();
        try {
            //  2  用jest执行语句
            SearchResult searchResult = jestClient.execute(search);
            //  3  接收并处理返回结果
            MetricAggregation aggregations = searchResult.getAggregations();
            List<TermsAggregation.Entry> buckets = aggregations.getTermsAggregation("groupby_" + type).getBuckets();
            nameValueDataList= changeResultListByType(  type,  buckets);

        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("查询ES异常");
        }
        return nameValueDataList;
    }


    //  1  构造查询语句 searchSourceBuilder
    //  2  用jest执行语句
    //  3  接收并处理返回结果
    @Override
    public Map getDetailByItem(String date, String itemName, Integer pageNo, Integer pageSize) {

        List detailList= new ArrayList();

        Map  resultMap = new HashMap();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //查询条件
        searchSourceBuilder.query(new MatchQueryBuilder("sku_name",itemName).operator(Operator.AND));
        //分页
        searchSourceBuilder.from((pageNo-1)*pageSize);
        searchSourceBuilder.size(pageSize);
        //确定字段
        searchSourceBuilder.fetchSource(new String[]{"create_time","sku_name","order_price","province_name","sku_num","total_amount","user_age","user_gender"},null);
        //高亮
        searchSourceBuilder.highlighter(new HighlightBuilder().field("sku_name"));

        Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex("gmall0609_order_wide_"+date).build();

        try {
            SearchResult searchResult = jestClient.execute(search);
            List<SearchResult.Hit<Map, Void>> hits = searchResult.getHits(Map.class);
            for (SearchResult.Hit<Map, Void> hit : hits) {
                Map source = hit.source;
                // 高亮字段覆盖普通字段
                String skuNameHL = hit.highlight.get("sku_name").get(0);
                source.put("sku_name",skuNameHL);
                detailList.add(hit.source);

            }
            //新版的es把 total值放在total/value中 而不是直接放在total   所以getTotal不好用 所以直接从结果对象中一层层找到对应的total值。
            Long total= searchResult.getJsonObject().getAsJsonObject("hits").getAsJsonObject("total").get("value").getAsLong();
            resultMap.put("total",total);
            resultMap.put("detail" ,detailList);
        } catch (IOException e) {
            e.printStackTrace();
        }


        return resultMap;




    }



}
